package controllers;

import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observer;

import model.AddNewLayersModel;
import model.EditLayersModel;
import model.LayerModel;
import model.SearchPhotoModel;
import model.UpdatePhotoLayersModel;
import view.SearchResultGUI;
import view.AddNewLayersGUI;
import view.UpdatePhotoLayersGUI;
import client.CliMessage;

/**
 * The Class UpdatePhotoLayersController.
 * Dmitry & Tomer
 */
public class UpdatePhotoLayersController extends AbstractController
{

	/** The update photo layers view. */
	private UpdatePhotoLayersGUI updatePhotoLayersView;
	
	/** The update photo layers model. */
	private UpdatePhotoLayersModel updatePhotoLayersModel;
	
	/** The layer list. */
	private ArrayList<LayerModel> layerList ;
	
	
	/**
	 * Instantiates a new update photo layers controller.
	 *
	 * @param theView the the view
	 * @param theModel the the model
	 */
	public UpdatePhotoLayersController(UpdatePhotoLayersGUI theView, UpdatePhotoLayersModel theModel) 
	{
		super(theView, theModel);
		updatePhotoLayersView = theView;
		updatePhotoLayersModel = theModel;
		updatePhotoLayersView.addAddNewLayerActionListener(new AddLayersBtnListener(this));
		updatePhotoLayersView.addEditExistingLayersActionListener(new EditLayers());
	}
	@Override
	public void handleDBRequestSuccess(){}

	/***
	 * if received a null search result - display a warning message and disable the edit layers button. 
	 */
	@Override
	public void handleNullSearchResult()
	{
		// The photo has no layers - display appropriate message
		updatePhotoLayersView.displayInfoMessage("This photo has no layers", "No layers found",2);
		//disable editing layers
		updatePhotoLayersView.enableEditButton(false);
	}

	/**
	 * get all layers of the photo from the DB and save them in a list.
	 * then, create a new data table and display it.
	 * */
	@Override
	public void handleDBSearchResult(CliMessage dbResult) 
	{
		//get the layer type, name and the link to file and save it to the model
		layerList = new ArrayList<LayerModel>();
		srs = dbResult.getSrs();
		int nRows = srs.size();
		
		//get all tuples
		for(int i = 0 ; i < nRows ; i++)
		{
			// get a tuple
			HashMap<String, String> layerTuple = srs.get(i);
			
			//get the time stamp , location and the link to file
			int layerType = Integer.parseInt(layerTuple.get("LAYERTYPE"));
			String layerName = layerTuple.get("LAYERNAME");
			String linkToFile = layerTuple.get("LINKTOFILE");
			
			//set a photo detail class
			LayerModel layerDetails = new LayerModel(layerType,layerName,linkToFile) ;
			
			//add the photo details to the list
			layerList.add(layerDetails);
			
			//display for developer
			System.out.println( layerName+" "+layerType+" "+linkToFile);
			
		}

		String dataTable[][] = createDataTable(srs);
		
		//create the model and view	
		EditLayersModel editLayersModel  = new EditLayersModel(layerList,updatePhotoLayersModel);
		SearchResultGUI editLayersView = new SearchResultGUI("Edit Photo Layers");
		editLayersView.setTable(getColumnNames(srs), dataTable);
		
		//set buttons according to user permissions
		String[] buttonNames;
		buttonNames = new String[2];
		buttonNames[0] = "View layer";
		buttonNames[1] = "Delete layer";
		
		//create all the buttons and save them to the model
		editLayersView.setAllbuttons(nRows, buttonNames);
		editLayersModel.setButtonNames(buttonNames);
		
		//create a new controller
		EditLayersController editLayersController = new EditLayersController(editLayersView,editLayersModel);
		
		//set the observer and back button listener
		setCurrentObserver(editLayersController);
		
		setBackListener(this,editLayersView);
		
		//display result window
		editLayersView.setVisible(true);
		editLayersView.displayInfoMessage("There are: "+nRows+" layers found","layers are found", 1);
		 
	}
	
	
	/**
	 * Creates the data table.
	 *
	 * @param srs the serialized result set
	 * @return the string[][]
	 */
	private String[][] createDataTable(ArrayList<HashMap<String, String>> srs)
	{
		int nRows = srs.size();
		int nCols = srs.get(0).keySet().size();
		
		//create data table
		 String[][] dataTable = new String[nRows][nCols];
		//get all keys
		 String[] columnNames = getColumnNames(srs);
		 	
		 //set data table
		 for (int j = 0; j < nRows; j++) 
		 {
			 for (int k = 0; k < nCols; k++) 
			 {
				 dataTable[j][k] = srs.get(j).get(columnNames[k]);
			 }
		 }
		 
		 return dataTable;
	}
	
	/**
	 * Gets the column names.
	 *
	 * @param srs the serialized result set
	 * @return the column names
	 */
	private String[] getColumnNames(ArrayList<HashMap<String, String>> srs)
	{
		int nCols = srs.get(0).keySet().size();
		 String[] columnNames = new String[nCols];
		 int i = 0;
		 for (String key : srs.get(0).keySet()) 
			 columnNames[i++] = key;
		 return columnNames;
	}
	
	/**
	 * The Class AddLayers.
	 * A listener to the add layers button
	 * @author Tomer
	 */
	class AddLayersBtnListener extends AbstractListener
	{
		private Observer previousObserver;

		public AddLayersBtnListener(Observer previousObserver) 
		{
			super();
			this.previousObserver = previousObserver;
		}
		
		/**
		 * when the add layer button is pressed - display the "add layers" window. 
		 * */
		@Override
		public void actionPerformed(ActionEvent e)
		{
			//get all the photo layers
			SearchPhotoModel aPhoto = updatePhotoLayersModel.getaPhoto();
			AddNewLayersModel addNewLayersModel = new AddNewLayersModel(aPhoto);
			AddNewLayersGUI addNewLayerView = new AddNewLayersGUI();
			AddNewLayersController addNewLayersController = new AddNewLayersController(addNewLayerView,addNewLayersModel);
			
			//set the observer and back button listener
			setCurrentObserver(addNewLayersController);
			
			setBackListener(previousObserver,addNewLayerView);
			
			//get the current layer list and set it to GUI
			String searchPhotoLayersQuery =	"search" 	+"SELECT * "
														+"FROM layertypes";
			sendToServer(searchPhotoLayersQuery);
			
		}

	}
	
	/**
	 * The Class EditLayers.
	 * A listener to the edit layers button.
	 * @author Tomer
	 */
	class EditLayers extends AbstractListener
	{
		@Override
		public void actionPerformed(ActionEvent e) 
		{
			
			//get all the photo layers from DB
			SearchPhotoModel aPhoto = updatePhotoLayersModel.getaPhoto();
			String timestamp = aPhoto.getTimeStamp();
			int location = aPhoto.getLocation();
			String searchPhotoLayersQuery =	"search" 	+"SELECT lt.LayerType , lt.LayerName , pl.LinkToFile "
														+"FROM photos AS p , photolayer AS pl, layertypes AS lt "
														+"WHERE pl.TimeStamp = p.TimeStamp "
														+"AND pl.Location = p.Location "
														+"AND lt.LayerType = pl.LayerType "
														+"AND p.TimeStamp = '"+timestamp+"' "
														+"AND p.Location = "+location;
			sendToServer(searchPhotoLayersQuery);
			
		}
		
	}	
}
